#!/usr/bin/env python
#-*- coding:utf-8 -*-

# arena.py
#
# Copyright (c) 2007 Marcelo Lira dos Santos
#
# Author: Marcelo Lira dos Santos <setanta@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA

import pygtk
pygtk.require('2.0')
import gtk
import gobject
import cairo
import math

from p_token import Token
from piemenu import PieMenu

LEFT_BUTTON = 1
RIGHT_BUTTON = 3

class Arena(gtk.DrawingArea):

    __gsignals__ = {
                    'realize': 'override',
                    'expose-event' : 'override',
                    'button-press-event' : 'override',
                    'button-release-event' : 'override',
                    'motion-notify-event' : 'override',
                    }

    def __init__(self):
        gtk.DrawingArea.__init__(self)
        self.add_events(gtk.gdk.BUTTON_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK |
                        gtk.gdk.BUTTON_RELEASE_MASK)

        self.tokens = []
        self.over_token = None
        self.menu = None
        self.hiding_menu = None

        #self.token_selected = None
        self.dragging = None


    def add_token(self, token):
        token.set_canvas(self)
        self.tokens.append(token)


    def do_realize(self):
        self.set_flags(self.flags() | gtk.REALIZED)

        events = gtk.gdk.EXPOSURE_MASK | gtk.gdk.BUTTON_PRESS_MASK | \
                 gtk.gdk.POINTER_MOTION_MASK

        self.window = gtk.gdk.Window(self.get_parent_window(),
                                     x=self.allocation.x,
                                     y=self.allocation.y,
                                     width=self.allocation.width,
                                     height=self.allocation.height,
                                     window_type=gtk.gdk.WINDOW_CHILD,
                                     wclass=gtk.gdk.INPUT_OUTPUT,
                                     visual=self.get_visual(),
                                     colormap=self.get_colormap(),
                                     event_mask=self.get_events() | events)

        self.window.set_user_data(self)
        self.style.attach(self.window)
        self.style.set_background(self.window, gtk.STATE_NORMAL)


    def do_expose_event(self, event):
        context = self.window.cairo_create()
        context.rectangle(event.area.x, event.area.y,
                          event.area.width, event.area.height)

        #if self.token_selected:
        #    if self.dragging:
        #        pos = self.dragging
        #        self._draw_round_area(context, pos)

        for token in self.tokens:
            token.draw(context)

        if self.menu:
            self.menu.draw(context)

        if self.hiding_menu:
            if self.hiding_menu.is_visible():
                self.hiding_menu.draw(context)
            else:
                self.hiding_menu = None

        return False


    def do_button_press_event(self, event):
        if event.button == LEFT_BUTTON:

            if self.over_token:
                #if self.over_token != self.token_selected:
                #    self.token_selected = self.over_token
                #    i = self.tokens.index(self.token_selected)
                #    self.tokens.append(self.tokens.pop(i))
                self.dragging = self.over_token.get_pos()
                #else:
                #    self.token_selected = None

                #self.refresh()


                if self.menu:
                    self.menu.hide()
                    self.hiding_menu = self.menu
                    self.menu = None

            elif self.menu:
                self.menu.button_press()

        return False


    def do_button_release_event(self, event):
        pos = (event.x, event.y)

        if event.button == LEFT_BUTTON:
            if self.dragging:
                self.dragging = None
                self.refresh()

            elif self.menu:
                self.menu.button_release(pos)

        elif event.button == RIGHT_BUTTON:
            if self.over_token and \
                    self.over_token.is_mouse_over(pos):

                #self.over_token.button_release()

                new_menu = self.over_token.get_menu()
                if self.menu:
                    self.menu.hide()
                    self.hiding_menu = self.menu

                if new_menu == self.menu:
                    self.menu = None
                else:
                    self.menu = new_menu
                    self.menu.show()

        return False


    def do_motion_notify_event(self, event):
        pos = (event.x, event.y)

        if self.dragging:
            #self.token_selected.set_pos(pos)
            self.over_token.set_pos(pos)
            self.refresh()
            return False

        for token in self.tokens:
            if token.is_mouse_over(pos):
                self.over_token = token
                self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))

                return False

        self.over_token = None

        if self.menu and self.menu.is_mouse_over(pos):
            self.refresh()
            self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
        elif not self.dragging:
            self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW))

        return False

        '''
        if self.drag:
            rect = self.get_allocation()
            x = rect.x + rect.width / 2
            y = rect.y + rect.height / 2

            radius = min(rect.width / 2, rect.height / 2) - 50
            distance = math.hypot(x - event.x, y - event.y)

            segment = radius / (self.max_value - self.min_value)
            point = int(round((distance / segment)) + self.min_value)

            if not self.values[self.attribute] == point:
                if point > self.modifiers[self.attribute] + 4 or \
                    point < self.modifiers[self.attribute] - 2 or \
                    point == self.values[self.attribute] + \
                    self.modifiers[self.attribute]:
                    return

                self.values[self.attribute] = point - self.modifiers[self.attribute]
                self.emit('value-changed', self.values)

                alloc = self.get_allocation()
                rect = gtk.gdk.Rectangle(0, 0, alloc.width, alloc.height)
                self.window.invalidate_rect(rect, True)
                self.window.process_updates(True)
        '''
        return False


    def refresh(self):
        alloc = self.get_allocation()
        rect = gtk.gdk.Rectangle(0, 0, alloc.width, alloc.height)
        self.window.invalidate_rect(rect, True)
        self.window.process_updates(True)


    def _draw_round_area(self, context, pos, radius=120):
        r, g, b = 0, 255, 0
        x, y = pos
        context.clip()
        context.set_source_rgba(r, g, b, 0.2)
        context.arc(x, y, radius, 0, 2 * math.pi)
        context.fill()


def test():
    window = gtk.Window()
    window.set_title('PieMenu')
    window.set_default_size(500, 400)

    arena = Arena()

    def do_callback(args):
        if args:
            number = args[0]
        else:
            number = None
        print 'icon #', number

    piemenu1 = PieMenu()
    piemenu1.add_item('edit-clear.png', do_callback, 2)
    piemenu1.add_item('edit-redo.png', do_callback, 3)
    piemenu1.add_item('edit-cut.png', do_callback)
    piemenu1.add_item('edit-undo.png', do_callback, 1)
    token1 = Token((200, 100), 'appointment-new.png', piemenu1)

    piemenu2 = PieMenu(radius=60)
    piemenu2.add_item('edit-redo.png', do_callback, 99)
    piemenu2.add_item('edit-undo.png', do_callback, 99)
    token2 = Token((300, 200), 'edit-cut.png', piemenu2)

    piemenu3 = PieMenu(radius=60)
    piemenu3.add_item('edit-redo.png', do_callback, 8)
    piemenu3.add_item('edit-undo.png', do_callback, 7)
    piemenu3.add_item('edit-cut.png', do_callback, 6)
    token3 = Token((150, 240), 'edit-clear.png', piemenu3)

    arena.add_token(token1)
    arena.add_token(token2)
    arena.add_token(token3)

    window.add(arena)
    window.connect('delete-event', gtk.main_quit)
    window.show_all()
    gtk.main()


if __name__ == '__main__':
    test()

